import csv
import time
import os
import sys
import datetime
from django.conf import settings
from trading.models import *
from analysis.basic_data import *

MONTH_DAYS = 22
YEAR1_DAYS = 248

MONITOR_RATE_UP = 5.0
MONITOR_RATE_DOWN = -5.0
MONITOR_DAYS = 22

def getDateFromStr(str):
    return datetime.datetime.strptime(str, "%Y-%m-%d %H:%M:%S").date()

class FundPrice:
    date = ""
    jjjz = 0.0 #基金净值
    ljjz = 0.0 #累计净值
    rate = 0.0 #日增长率
    rateYear = 0.0 #最近1年的收益
    rateYear3 = 0.0 #最近3年的收益
    rateYear5 = 0.0 #最近5年的收益

class FundIncome:
    units = 0.0 #基金份额
    cost = 0.0 # 平均成本
    totalCost = 0.0 # 总成本
    incomeTotal = 0.0 # 累计收益
    income = 0.0 #基金收益
    incomePercent = 0.0 #收益率
    incomeDay = 0.0 #当日收益

class FundTradingData:
    date = ""
    units = 0.0
    cost = 0.0

class PriceAnalysis:
    monitorDay = MONITOR_DAYS
    monitorRate1 = MONITOR_RATE_DOWN
    monitorRate2 = MONITOR_RATE_UP
    monitorResult = []

    priceDir = ""
    incomeDir = ""
    code = ""
    price = []
    income = []

    def __init__(self, code):
        self.code = code
        self.price = []
        self.income = []
        return

    def setPriceDir(self, dir):
        self.priceDir = dir
        return

    def readPriceData(self):
        path = settings.FUND_PRICE_DIR + "/" + self.code + ".csv"
        csvReader = csv.reader(open(path, encoding='utf-8'))
        count = 0
        jjjz = 0.0
        ljjz = 0.0
        for line in csvReader:
            count = count + 1
            priceTmp = FundPrice()
            priceTmp.date = getDateFromStr(line[0])
            priceTmp.jjjz = float(line[1])
            priceTmp.ljjz = float(line[2])
            priceTmp.rate = self.calcRate(jjjz, ljjz, priceTmp.ljjz)
            self.price.append(priceTmp)
            jjjz = priceTmp.jjjz
            ljjz = priceTmp.ljjz
            #print(getTimeStr(priceTmp.date), priceTmp.jjjz, priceTmp.ljjz, priceTmp.rate)
        # print("read", len(self.price), "price datas for price_analysis", self.code)
        self.getYearBeforeDateIndex(1)
        return

    def calcRate(self, jjjz, ljjz1, ljjz2):
        if jjjz == 0.0:
            return 0.0

        rate = (ljjz2 - ljjz1) * 100 / jjjz
        return round(rate, 2)

    def calcCYData(self):
        # code, rate
        lst = [self.code]
        rateIndex = 1
        firstPrice = self.price[0]
        lastPrice = self.price[0]
        calcYear = self.price[0].date.year
        for price in self.price:
            year = price.date.year
            if calcYear != year:
                # year变化，开始计算前一个year的数据
                rate = (lastPrice.ljjz - firstPrice.ljjz) * 100 / firstPrice.jjjz
                rate = round(rate, 2)
                lst.insert(rateIndex, rate)

                # 更新year
                firstPrice = price
                calcYear = year
                
            lastPrice = price
        if firstPrice != self.price[-1]:
            lastPrice = self.price[-1]
            rate = (lastPrice.ljjz - firstPrice.ljjz) * 100 / firstPrice.jjjz
            rate = round(rate, 2)
            lst.insert(rateIndex, rate) 
        return lst

    def calcIncomeRateByDays(self, days):
        count = len(self.price)
        index = count - 1
        rate = 0.0
        if count > days:
            rate = (self.price[index].ljjz - self.price[count - days].ljjz) * 100 / self.price[count - days].jjjz
        return round(rate, 2)

    def calcIncomeRateByIndex(self, index):
        if index == -1:
            return 0.0

        rate = (self.price[-1].ljjz - self.price[index].ljjz) * 100 / self.price[index].jjjz
        return round(rate, 2)

    def getYearBeforeDateIndex(self, yearCount):
        from dateutil.relativedelta import relativedelta
        if self.price != None or len(self.price) == 0:
            return -1
        lastDay = self.price[-1].date
        lastYear = lastDay - relativedelta(years=yearCount)

        for i in range(len(self.price)-1, 0, -1):
            if lastYear >= self.price[i].date:
                return i
        return -1

    def getMonthBeforeDateIndex(self, monthCount):
        from dateutil.relativedelta import relativedelta
        lastDay = self.price[-1].date
        lastYear = lastDay - relativedelta(months=monthCount)

        for i in range(len(self.price)-1, 0, -1):
            if lastYear >= self.price[i].date:
                return i
        return -1

    def calcMonthIncomeRate(self, month):
        index = self.getMonthBeforeDateIndex(month)
        return self.calcIncomeRateByIndex(index)
        # return self.calcIncomeRateByDays(month*22)

    def calcYearIncomeRate(self, years):
        index = self.getYearBeforeDateIndex(years)
        return self.calcIncomeRateByIndex(index)
        # return self.calcIncomeRateByDays(years*245)

    def calcYearRate(self):
        # 一年按照254天交易日算，不到一年的数据按照比例计算
        Y1 = 245
        Y2 = Y1 * 2
        Y3 = Y1 * 3
        Y5 = Y1 * 5
        count = len(self.price)

        if count == 0:
            return 0.0, 0.0, 0.0

        rateYear1 = 0.0
        rateYear2 = 0.0
        rateYear3 = 0.0
        rateYear5 = 0.0

        index = count - 1
        rateYears = []
        for i in range(0, count//Y1):
            index1 = index - i * Y1
            index2 = index - (i + 1) * Y1
            rate = (self.price[index1].ljjz - self.price[index2].ljjz) * 100 / self.price[index2].ljjz
            rateYears.append(round(rate, 2))
        if (len(rateYears) > 5):
            rateYears = rateYears[0:5]

        if count < Y1:
            rateYear1 = (self.price[index].ljjz - self.price[0].ljjz) * Y1 * 100 / (count * self.price[0].jjjz)
            #rateYear3 = rateYear1 * 3
            #rateYear5 = rateYear1 * 5
        elif count < Y2:
            # print(self.price[index].ljjz - self.price[count - Y1].ljjz, self.price[count - Y1].jjjz)
            rateYear1 = (self.price[index].ljjz - self.price[count - Y1].ljjz) * 100 / self.price[count - Y1].jjjz
            #rateYear2 = (self.price[index].ljjz - self.price[0].ljjz) * Y2 * 100 / (count * self.price[0].jjjz)
            #rateYear3 = rateYear2 * 3 / 2
            #rateYear5 = rateYear2 * 5 / 2
        elif count < Y3:
            # print(self.price[index].ljjz - self.price[count - Y1].ljjz, self.price[count - Y1].jjjz)
            rateYear1 = (self.price[index].ljjz - self.price[count - Y1].ljjz) * 100 / self.price[count - Y1].jjjz
            rateYear2 = (self.price[index].ljjz - self.price[count - Y2].ljjz) * 100 / self.price[count - Y2].jjjz
            #rateYear3 = (self.price[index].ljjz - self.price[0].ljjz) * Y3 * 100 / (count * self.price[0].jjjz)
            #rateYear5 = rateYear3 * 5 / 3
        elif count < Y5:
            rateYear1 = (self.price[index].ljjz - self.price[count - Y1].ljjz) * 100 / self.price[count - Y1].jjjz
            rateYear2 = (self.price[index].ljjz - self.price[count - Y2].ljjz) * 100 / self.price[count - Y2].jjjz
            rateYear3 = (self.price[index].ljjz - self.price[count - Y3].ljjz) * 100 / self.price[count - Y3].jjjz
            #rateYear5 = (self.price[index].ljjz - self.price[0].ljjz) * Y5 * 100 / (count * self.price[0].jjjz)
        else:
            #print(count, self.price[index].ljjz, self.price[count - Y1].ljjz, self.price[count - Y1].jjjz, getTimeStr(self.price[count - Y1].date))
            rateYear1 = (self.price[index].ljjz - self.price[count - Y1].ljjz) * 100 / self.price[count - Y1].jjjz
            rateYear2 = (self.price[index].ljjz - self.price[count - Y2].ljjz) * 100 / self.price[count - Y2].jjjz
            rateYear3 = (self.price[index].ljjz - self.price[count - Y3].ljjz) * 100 / self.price[count - Y3].jjjz
            rateYear5 = (self.price[index].ljjz - self.price[count - Y5].ljjz) * 100 / self.price[count - Y5].jjjz     

        return round(rateYear1, 2), round(rateYear2, 2), round(rateYear3, 2), round(rateYear5, 2), rateYears

    def rateMonitor(self, maxDrawDown1Y):
        price = self.price
        startIndex = 0
        if len(price) > self.monitorDay:
            startIndex = len(price) - 1 - self.monitorDay

        # 先找到找最大值和最小值的位置
        maxIndex = 0
        maxValue = 0.0
        for i in range(startIndex, len(price)):
            if maxValue <= price[i].ljjz:
                maxValue = price[i].ljjz
                maxIndex = i

        minIndex = 0
        minValue = 99999.0
        for i in range(startIndex, len(price)):
            if minValue >= price[i].ljjz:
                minValue = price[i].ljjz
                minIndex = i

        lastPrice = price[-1]
        rateMin = round((lastPrice.ljjz - price[maxIndex].ljjz) * 100 / lastPrice.jjjz, 2)
        rateMax = round((lastPrice.ljjz - price[minIndex].ljjz) * 100 / lastPrice.jjjz, 2)

        result = 0
        if rateMax > self.monitorRate2 or rateMin < self.monitorRate1:
            result = 1
            return rateMin, price[maxIndex].date, rateMax, price[minIndex].date, result

        maxDrawDown = 0.0
        if maxDrawDown1Y != None:
            maxDrawDown = maxDrawDown1Y
        else:
            maxDrawDown = BasicData.getMaxDrawDownYear(self.code)

        if maxDrawDown * 0.5 > rateMin and rateMin > 0.5: #下跌回撤的50%，报2级告警
            result = 2

        return rateMin, price[maxIndex].date, rateMax, price[minIndex].date, result

class PriceAnalysisTask:
    priceDir = ""
    analysisDir = ""
    yearRate = []
    cyData = [] # 自然年统计数据

    def setPriceDir(self, priceDir):
        self.priceDir = priceDir
        return

    def setAnalysisDir(self, analysisDir):
        self.analysisDir = analysisDir
        return

    def analyzeAllFund(self):
        print('analyzeAllFund')
        tradings = BasicData.getTradingFundLstFromDB()
        for item in tradings:
            code = item.code

            # analysis
            analysis = PriceAnalysis(code)
            analysis.setPriceDir(self.priceDir)
            analysis.readPriceData()
            cyData = analysis.calcCYData()
            self.cyData.append(cyData)
            y1, y2, y3, y5, lst = analysis.calcYearRate()
            self.yearRate.append([code, y1, y3, y5, lst])
        
            info = FundInfoBriefData()
            rate1M = analysis.calcMonthIncomeRate(1)
            rate3M = analysis.calcMonthIncomeRate(3)
            rate6M = analysis.calcMonthIncomeRate(6)
            # rate1Y = analysis.calcYearIncomeRate(1)
            # rate2Y = analysis.calcYearIncomeRate(2)
            # rate3Y = analysis.calcYearIncomeRate(3)
            # rate5Y = analysis.calcYearIncomeRate(5)
            info.refreshMonthIncomeRate(code, rate1M, rate3M, rate6M)
            info.refreshYearIncomeRate(code, y1, y2, y3, y5)
            # print("refreshYearIncomeRate:", code, rate1Y, rate2Y, rate3Y, rate5Y, y1, y3, y5, lst)
            # info.refreshYearIncomeRate(code, rate1Y, rate2Y, rate3Y, rate5Y)

            avg1M = BasicData.getAvgPrice(code, analysis.price, MONTH_DAYS)
            avg6M = BasicData.getAvgPrice(code, analysis.price, YEAR1_DAYS / 2)
            avg1Y = BasicData.getAvgPrice(code, analysis.price, YEAR1_DAYS)
            info.refreshPriceAvg(code, avg1M, avg6M, avg1Y)

            maxDrawDown1Y = BasicData.gtMaxDrawDown(code, YEAR1_DAYS, YEAR1_DAYS)
            maxDrawDown2Y = BasicData.gtMaxDrawDown(code, YEAR1_DAYS*2, YEAR1_DAYS)
            maxDrawDown3Y = BasicData.gtMaxDrawDown(code, YEAR1_DAYS*3, YEAR1_DAYS)
            maxDrawDown5Y = BasicData.gtMaxDrawDown(code, YEAR1_DAYS*5, YEAR1_DAYS)
            info.refreshMaxDrawDown(code, maxDrawDown1Y, maxDrawDown2Y, maxDrawDown3Y, maxDrawDown5Y)

            rateMin, priceMaxDate, rateMax, priceMinDate, alarm = analysis.rateMonitor(maxDrawDown1Y)
            alarmText = str(priceMaxDate) + "," + str(rateMin) + "," + str(priceMinDate) + "," + str(rateMax)
            info.refreshAlarm(code, alarm, alarmText)

        self.writeYearRate(self.yearRate)
        self.writeCYRate(self.cyData)
        return

    def writeYearRate(self, yearRate):
        filename = self.analysisDir + "year_rate.csv"
        with open(filename, "w", newline='') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(["code", "rateY1", "rateY3", "rateY5", "lst"])
            writer.writerows(yearRate)
            print("write year rate end1.")
    
    def writeCYRate(self, rate):
        filename = self.analysisDir + "civil_year_rate.csv"
        with open(filename, "w", newline='') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerows(rate)
            print("write civil year rate end.")


